package collector

import (
	"fmt"
	"github.com/go-kit/kit/log"
	"github.com/prometheus/client_golang/prometheus"
	"http_monitor/models"
	"http_monitor/rule"
	"http_monitor/single"
	"http_monitor/utils"
	"strconv"
	"sync"
	"time"
)

type httpCollector struct {
	requestTime *prometheus.Desc
	logger      log.Logger
}

func init() {
	registerCollector("http", defaultEnabled, NewHttpCollector)
}

// NewHttpCollector returns a new Collector exposing ARP stats.
func NewHttpCollector(logger log.Logger) (Collector, error) {
	return &httpCollector{
		requestTime: prometheus.NewDesc(
			prometheus.BuildFQName(namespace, "http", "request_time"),
			"aegis http request time",
			[]string{"name", "address", "area"}, nil,
		),
		logger: logger,
	}, nil
}
func getRequestTime() (chan map[string]interface{}, error) {
	var wg sync.WaitGroup
	fmt.Println(time.Now())

	result, err := models.GetApis()
	if err != nil {
		return nil, err
	}
	c := make(chan map[string]interface{}, len(result))
	for _, v := range result {
		wg.Add(1)

		go func(v models.Apis) {
			result := make(map[string]interface{})
			defer wg.Done()
			nanosecond := time.Now().Nanosecond()
			body, doTime, code, _ := utils.HttpRequest(v.Url+"?t="+strconv.Itoa(nanosecond), v.Timeout, v.Method, "")
			factory := rule.Factory{Rule: v.VerifyRule}
			rule := factory.GetRule()
			result["requestTime"] = doTime
			source := ""
			if v.VerifyType == "body" {
				source = body

			} else if v.VerifyType == "code" {
				source = strconv.Itoa(code)
			}
			if !rule.Verify(source, v.VerifyValue) {
				result["requestTime"] = -5000
			}
			result["models"] = v

			c <- result

		}(v)

	}
	wg.Wait()
	return c, nil
}
func (c *httpCollector) Update(ch chan<- prometheus.Metric) error {
	r, err := getRequestTime()

	if err != nil {
		return fmt.Errorf("could not get ARP entries: %s", err)
	}
	close(r)
	for value := range r {

		httpApi := value["models"].(models.Apis)
		ch <- prometheus.MustNewConstMetric(
			c.requestTime, prometheus.GaugeValue, interface2float(value["requestTime"]),
			httpApi.Name, httpApi.Url, single.GetInstance().Area)
	}

	return nil
}
func interface2float(inter interface{}) float64 {

	switch inter.(type) {

	case int64:
		return float64(inter.(int64))
	case int:

		return float64(inter.(int))

	}
	return 0

}
